<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/8/24
 * Time: 16:31
 */

//唯一直接被入口文件访问的类文件,
//实现初始化项目,拆分url,调用对应控制器和方法

//定义命名空间
namespace Shop;

//判断是否有常量
if(!defined('SHOP')){
    header("Location:../index.php");
    exit;
}

//定义核心类
class App{
    //定义入口
    public static function Run(){
        //1.初始化字符集
        self::setCharset();
        //2.初始化目录常量
        self::setDir();
        //3.初始化配置
        self::setConfig();
        //4.初始化错误
        self::setError();
        //注册自动加载
        self::setSpl();
        //5.初始化url
        self::setUrl();
    }

    //1.设置字符集
    private static function setCharset(){
        header("Content-type:text/html;charset=utf-8");
    }

    //2.设置目录常量,方便后续快速访问文件
    private static function setDir(){
        $dir=str_replace("\\",'/',$_SERVER['DOCUMENT_ROOT']); //定义网站根目录

        define("SHOP_DIR",$dir.'/'); //根目录
        define("SHOP_CORE",$dir.'/Core/');  //核心目录
        define("SHOP_PUBLIC",$dir.'/Public/');  //资源目录
        define("SHOP_CONFIG",$dir.'/Config/');  //配置目录

        define("SHOP_CONTROLLER",$dir.'/Application/'.SHOP.'/Controller/');  //控制器目录
        define("SHOP_MODEL",$dir.'/Application/'.SHOP.'/Model/');  //模型目录
        define("SHOP_VIEW",$dir.'/Application/'.SHOP.'/View/');  //视图目录
    }

    //3.加载配置
    private static function setConfig(){
        $GLOBALS['Config']=include SHOP_CONFIG.'config.php';
    }

    //4.设置错误
    private static function setError(){
        //设置错误提示
        @ini_set('display_errors',$GLOBALS['Config']['display_errors']);
        @ini_set('error_reporting',$GLOBALS['Config']['error_reporting']);
    }

    //设置自动加载机制
    private static function setSpl(){
        //注册自动加载机制,自动加载 控制器,模型,核心类
        //注册自动加载在类里面使用,需要传递,类名和方法名
        spl_autoload_register(array(self,'autoCore'));
        spl_autoload_register(array(self,'autoController'));
        spl_autoload_register(array(self,'autoModel'));
    }

    //自动加载核心类
    private static function autoCore($a){
        //$a 携带了命名空间,但是对应的类文件没有命名空间,所以需要去掉命名空间
        $a=basename($a); //去掉命名空间
        $a=SHOP_CORE.$a.'.class.php';
        if(is_file($a)){
            include $a;
        }
    }

    //自动加载控制器类
    private static function autoController($a){
        //$a 携带了命名空间,但是对应的类文件没有命名空间,所以需要去掉命名空间
        $a=basename($a); //去掉命名空间
        $a=SHOP_CONTROLLER.$a.'.class.php';
        if(is_file($a)){
            include $a;
        }
    }

    //自动加载模型类
    private static function autoModel($a){
        //$a 携带了命名空间,但是对应的类文件没有命名空间,所以需要去掉命名空间
        $a=basename($a); //去掉命名空间
        $a=SHOP_MODEL.$a.'.class.php';
        if(is_file($a)){
            include $a;
        }else{
            exit('类文件不存在');
        }
    }


    //5.拆分url,根据不同的参数 C 和 F 得到不同的控制器和方法,实现单一入口
    private static function setUrl(){
        //C 代表控制器
        //F 代表方法
        //接收参数
        $C=isset($_REQUEST['C'])?$_REQUEST['C']:"Index";
        $F=isset($_REQUEST['F'])?$_REQUEST['F']:'index';
        //得到控制器类
        $C="\\Controller\\".$C.'Controller';
        $obj=new $C(); //实例化控制器
        //保存控制器和方法到常量
        define("SHOP_C",basename($C));
        define("SHOP_F",$F);
        //调用方法
        //method_exists() 判断对象是否存在对应方法
        if(method_exists($obj,$F)){
            $obj->$F();
        }else{
            exit('方法不存在');
        }

    }

}